package com.modules.schedule.utils;

import cn.hutool.core.util.StrUtil;
import com.common.bean.config.SpringContextHolder;
import com.common.enums.CommonEnum;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.modules.schedule.entity.ScheduleJobLog;
import com.modules.schedule.service.ScheduleJobLogService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.concurrent.*;

/**
 * 定时任务
 *
 */
@Slf4j
public class ScheduleJob extends QuartzJobBean {

    private ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();

    private ExecutorService service = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), namedThreadFactory);

    @Override
    protected void executeInternal(JobExecutionContext context) {
        com.modules.schedule.entity.ScheduleJob scheduleJob = new com.modules.schedule.entity.ScheduleJob();

        BeanUtils.copyProperties(context.getMergedJobDataMap().get(com.modules.schedule.entity.ScheduleJob.JOB_PARAM_KEY), scheduleJob);
        //获取spring bean
        ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService) SpringContextHolder.getBean("scheduleJobLogService");

        //数据库保存执行记录
        ScheduleJobLog logEntity = new ScheduleJobLog();
        logEntity.setJobId(scheduleJob.getId().toString());
        logEntity.setBeanName(scheduleJob.getBeanName());
        logEntity.setMethodName(scheduleJob.getMethodName());
        logEntity.setParams(scheduleJob.getParams());

        //任务开始时间
        long startTime = System.currentTimeMillis();

        try {
            //执行任务
            log.info(StrUtil.format("任务准备执行，任务：{}[{}]，表达式：{}", scheduleJob.getName(), scheduleJob.getId(), scheduleJob.getCronExpression()));
            ScheduleRunnable task = new ScheduleRunnable(scheduleJob.getBeanName(),
                    scheduleJob.getMethodName(), scheduleJob.getParams());
            Future<?> future = service.submit(task);

            future.get();

            //任务执行总时长
            long times = System.currentTimeMillis() - startTime;
            logEntity.setTimes((int) times);
            //任务状态    0：成功    1：失败
            logEntity.setStatus(CommonEnum.VALID.getCode());

            log.info(StrUtil.format("任务执行完毕，任务：{}[{}]，表达式：{}，总共耗时：{}毫秒", scheduleJob.getName(), scheduleJob.getId(), scheduleJob.getCronExpression(), times));
        } catch (Exception e) {
            log.info(StrUtil.format("任务执行失败，任务：{}[{}]，表达式：{}", scheduleJob.getName(), scheduleJob.getId(), scheduleJob.getCronExpression()));

            //任务执行总时长
            long times = System.currentTimeMillis() - startTime;
            logEntity.setTimes((int) times);

            //任务状态    0：成功    1：失败
            logEntity.setStatus(CommonEnum.INVALID.getCode());
            logEntity.setError(StrUtil.sub(e.toString(), 0, 2000));
        } finally {
            scheduleJobLogService.save(logEntity);
        }
    }
}
